package cn.tianyigps.obd.handler;

import cn.tianyigps.obd.beans.Equipment;
import cn.tianyigps.obd.beans.StandardModel;
import cn.tianyigps.obd.cache.ChannelCache;
import cn.tianyigps.obd.factorys.EquipmentFactory;
import cn.tianyigps.obd.pipelines.TYChannelPipeline;
import cn.tianyigps.obd.utils.MessageCoding;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.List;
import java.util.Optional;

import static cn.tianyigps.obd.Storer.store;


/**
 * Created with IDEA
 *
 * @description: 设备处理类
 * @author: cui.guibin
 * @create: 2019/3/7 10:20
 **/
public class EquipmentHandler extends ChannelInboundHandlerAdapter {

    static Logger log = LogManager.getLogger(EquipmentHandler.class);

    public boolean init(ChannelHandlerContext ctx, Object msg) {
        ByteBuf byteBuf = ((ByteBuf) msg).copy();
        TYChannelPipeline pipeline = (TYChannelPipeline) ctx.pipeline();
        byte[] bytes = MessageCoding.getBytes(byteBuf);
        String strData = MessageCoding.bytesToHexString(bytes);
        log.warn("in {}",strData);
        if (!strData.toUpperCase().startsWith("7E")|| !strData.toUpperCase().endsWith("7E"))
            log.error("Epackage {}",strData);
//        Storer.store2Disk(strData,"original","D:/log.txt");
//        Storer.store2Disk(strData,"original","/usr/local/java/logs/log.txt");
        if (!strData.toUpperCase().endsWith("7E")){
            strData = strData + "7e";
        }
        Equipment equipment = pipeline.getEquipment();
        if (!Optional.ofNullable(equipment).isPresent()) {
            equipment = EquipmentFactory.equipmentInstance(strData);
            if (Optional.ofNullable(equipment).isPresent()) {
                pipeline.setEquipment(equipment);
                ChannelCache<String, ChannelHandlerContext> instance = ChannelCache.getInstance();
                instance.put(equipment.getEquipmentId(), ctx);
            }
        }

        if (!Optional.ofNullable(equipment).isPresent())
            return false;
        // 注册回复
        byte[] response = equipment.response(strData);
        if (response !=null && response.length > 0)
            ctx.writeAndFlush(Unpooled.copiedBuffer(response));
        // 通用回复
        byte[] generalResponse = equipment.generalResponse(strData);
        if (generalResponse !=null && generalResponse.length > 0)
            ctx.writeAndFlush(Unpooled.copiedBuffer(generalResponse));
        // 指令下发
        byte[] command = equipment.command(strData);
        if (command !=null && command.length > 0)
            ctx.writeAndFlush(Unpooled.copiedBuffer(command));
        return true;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//        ((ByteBuf)msg).retain(2);
        boolean init = init(ctx, msg);
        if (!init)
            return;
        TYChannelPipeline pipeline = (TYChannelPipeline) ctx.pipeline();
        Equipment equipment = pipeline.getEquipment();
        List<StandardModel> standardModels = equipment.analysisPackageType(msg);
        store("3",standardModels);
//        ReferenceCountUtil.release(msg);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        super.channelReadComplete(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        TYChannelPipeline pipeline = (TYChannelPipeline) ctx.pipeline();
        Equipment equipment = pipeline.getEquipment();
        if (Optional.ofNullable(equipment).isPresent())
            log.error("设备: "+ equipment.getEquipmentId() +"   type： "+ equipment.getType() +" 报错");
        super.exceptionCaught(ctx, cause);
    }
}
